package com.gang.lingdian.load;


import java.io.FileInputStream;
import java.lang.reflect.Method;

/**
 * @author gyg
 * @date 2021/11/11 21:54
 * desc 自定义类加载器
 */
public class MyClassLoaderTest {

    static class MyClassLoader extends ClassLoader {

        private String classPath;

        public MyClassLoader(String classPath) {
            this.classPath = classPath;
        }
        private byte[] loadByte(String name) throws Exception {
            name = name.replaceAll("\\.", "/");
            FileInputStream fis = new FileInputStream(classPath + "/" + name
                    + ".class");
            int len = fis.available();
            byte[] data = new byte[len];
            fis.read(data);
            fis.close();
            return data;
        }

        @Override
        public Class<?> loadClass(String name,boolean resolve) throws ClassNotFoundException {
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                Class<?> c = findLoadedClass(name);
                if (c == null) {
                    long t0 = System.nanoTime();
                    //双亲委派
                    // try {
                    //     if (parent != null) {
                    //         c = parent.loadClass(name, false);
                    //     } else {
                    //         c = findBootstrapClassOrNull(name);
                    //     }
                    // } catch (ClassNotFoundException e) {
                    //     // ClassNotFoundException thrown if class not found
                    //     // from the non-null parent class loader
                    // }

                    if (c == null) {
                        // If still not found, then invoke findClass in order
                        // to find the class.
                        long t1 = System.nanoTime();
                        c = findClass(name);

                        // this is the defining class loader; record the stats
                        sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        sun.misc.PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {
                byte[] bytes = loadByte(name);
                return defineClass(name,bytes,0,bytes.length);
            } catch (Exception e){
                e.printStackTrace();
                throw new ClassNotFoundException();
            }
        }
    }


    public static void main(String[] args) throws Exception {
        // 初始化自定义类加载器，会先初始化父类加载器classLoader，其中会把自定义类加载器的父加载器设置为应用程序类加载器AppClassLoader
        MyClassLoader  classLoader = new MyClassLoader("/Users/gang/test");
        Class<?> clazz = classLoader.loadClass("com.gang.lingdian.auxiliary.User1");
        Object instance = clazz.newInstance();
        Method method = clazz.getDeclaredMethod("out", null);
        method.invoke(instance,null);
        System.out.println(clazz.getClassLoader().getClass().getName());
    }


}
